import 'dart:async';
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:flutter_aliplayer/flutter_aliplayer.dart';
import 'package:flutter_aliplayer/flutter_aliplayer_factory.dart';
import 'package:get/get.dart';
import 'package:logger/logger.dart';
import 'package:screen_brightness/screen_brightness.dart';
import 'package:ball_lion/service/config_service.dart';
import 'package:ball_lion/utils/date_time_utils.dart';
import 'package:ball_lion/routes/routes.dart';
import 'package:ball_lion/utils/utils.dart';
import 'package:ball_lion/module/overlay/live_float_widget.dart';
import 'package:volume_controller/volume_controller.dart';

enum PlayStatus {
  idle(name: "idle", value: 0),
  initialized(name: "initialized", value: 1),
  prepared(name: "prepared", value: 2),
  started(name: "started", value: 3),
  paused(name: "paused", value: 4),
  stopped(name: "stopped", value: 5),
  completion(name: "completion", value: 6),
  error(name: "error", value: 7);

  final String name;
  final int value;
  const PlayStatus({required this.name, required this.value});

  static PlayStatus status(int type) {
    switch (type) {
      case 0:
        return idle;
      case 1:
        return initialized;
      case 2:
        return prepared;
      case 3:
        return started;
      case 4:
        return paused;
      case 5:
        return stopped;
      case 6:
        return completion;
      case 7:
        return error;
      default:
        return idle;
    }
  }
}

class QsPlayerLogic extends GetxController {
  final bool autoPlay;
  QsPlayerLogic({this.autoPlay = true});

  String _url = "";
  late FlutterAliplayer player =
      FlutterAliPlayerFactory.createAliPlayer(playerId: autoPlay ? "33" : "1");
  PlayStatus _status = PlayStatus.idle;
  double _width = Get.width;
  double height = Get.height;
  String? _matchInfo;
  bool _firstVolume = true;
  double _trueVolume = 0;
  double _originVolume = 0;
  double _originBrightness = 0;
  double _startBrightness = 0;
  int _volumeLevel = 0;
  int _brightnessLevel = 0;
  int _duration = 0;
  int _currentPosition = 0;
  double _slidePosition = 0;
  bool _startSlide = false;
  bool _onSlide = false;
  int? _currentViewId;
  AppLifecycleListener? _lifecycleListener;
  Timer? _createTimer;
  int? _errorCode;
  Completer? _completer;
  bool setFirst = false;

  String get slideTime {
    var currentTime =
        DateTime.fromMillisecondsSinceEpoch(slidePosition.toInt(), isUtc: true);
    return <String>[
      if (currentTime.hour > 0) "${currentTime.hour}:",
      currentTime.formatedString('mm:ss')
    ].join();
  }

  String get positionTime {
    var currentTime =
        DateTime.fromMillisecondsSinceEpoch(currentPosition, isUtc: true);
    return <String>[
      if (currentTime.hour > 0) "${currentTime.hour}:",
      currentTime.formatedString('mm:ss')
    ].join();
  }

  String get totalTime {
    var total = DateTime.fromMillisecondsSinceEpoch(duration, isUtc: true);
    return <String>[
      if (total.hour > 0) "${total.hour}:",
      total.formatedString('mm:ss')
    ].join();
  }

  bool get firstVolume => _firstVolume;
  double get originVolume => _originVolume;
  double get trueVolume => _trueVolume;
  double get originBrightness => _originBrightness;
  PlayStatus get status => _status;
  String? get matchInfo => _matchInfo;
  int get duration => _duration;
  int get currentPosition => _currentPosition;
  double get slidePosition => _slidePosition;
  bool get startSlide => _startSlide;
  bool get onSlide => _onSlide;
  double get startBrightness => _startBrightness;
  int get brightnessLevel => _brightnessLevel;
  int get volumeLevel => _volumeLevel;
  String get url => _url;
  bool get canSmall => status == PlayStatus.started && duration == 0;
  double get width => _width;
  int? get currentViewId => _currentViewId;
  int? get errorCode => _errorCode;
  Completer get completer {
    _completer ??= Completer();
    return _completer!;
  }

  set errorCode(int? value) {
    _errorCode = value;
    update();
  }

  set currentViewId(int? value) {
    _currentViewId = value;
    update();
  }

  set width(double value) {
    _width = value;
    update();
  }

  set url(String value) {
    _url = value;
    update();
  }

  set volumeLevel(int value) {
    _volumeLevel = value;
    update();
  }

  set brightnessLevel(int value) {
    _brightnessLevel = value;
    update();
  }

  set startBrightness(double value) {
    _startBrightness = value;
    update();
  }

  set onSlide(bool value) {
    _onSlide = value;
    update();
  }

  set startSlide(bool value) {
    _startSlide = value;
    update();
  }

  set slidePosition(double value) {
    if (value < 0) {
      _slidePosition = 0;
    } else if (value > duration) {
      _slidePosition = duration.toDouble();
    } else {
      _slidePosition = value;
    }
    update();
  }

  set currentPosition(int value) {
    _currentPosition = value;
    update();
  }

  set duration(int value) {
    _duration = value;
    update();
  }

  set matchInfo(String? value) {
    _matchInfo = value;
    update();
  }

  set status(PlayStatus value) {
    if (_status != PlayStatus.completion) _status = value;
    update();
  }

  set originBrightness(double value) {
    _originBrightness = value;
    update();
  }

  set trueVolume(double value) {
    if (value > 1) {
      _trueVolume = 1;
    } else if (value < 0) {
      _trueVolume = 0;
    } else {
      _trueVolume = value;
    }
    log(_trueVolume.toString());
    update();
  }

  set originVolume(double value) {
    _originVolume = value;
    update();
  }

  set firstVolume(bool value) {
    _firstVolume = value;
    update();
  }

  @override
  void onInit() async {
    FlutterAliPlayerFactory.loadRtsLibrary();
    player.setScalingMode(FlutterAvpdef.AVP_SCALINGMODE_SCALETOFILL);
    player.setAutoPlay(autoPlay);
    player.setOnCompletion((playerId) {
      Logger().d("当前状态：${PlayStatus.completion.name}");
      status = PlayStatus.completion;
      update();
    });
    player.setOnError((code, errorExtra, errorMsg, playerId) {
      if (errorMsg?.contains("Prepare url is empty") ?? false) return;
      Logger().d("播放错误：$errorMsg");
      status = PlayStatus.error;
      if (code.hasValue) errorCode = code;
      update();
    });
    player.setOnPrepared((playerId) async {
      Logger().d("当前状态：${PlayStatus.prepared}");
      if (width < Get.width) width = Get.width;
      try {
        status = PlayStatus.prepared;
      } catch (e) {
        Logger().d(e);
      }
      if (!autoPlay) {
        player.play();
      }
      await player.getMediaInfo().then((value) {
        duration = value["duration"];
      });
      update();
    });
    player.setOnRenderingStart((playerId) async {
      Logger().d("当前状态：${PlayStatus.started}");
      status = PlayStatus.started;
      update();
    });
    player.setOnInfo((infoCode, extraValue, extraMsg, playerId) {
      if (infoCode == FlutterAvpdef.CURRENTPOSITION) {
        if (extraValue.hasValue) currentPosition = extraValue!;
        if (!onSlide && startSlide) startSlide = false;
      }
    });
    player.setOnVideoSizeChanged(
        (videoWidth, videoHeight, rotation, playerId) async {
      bool needChange = false;
      if (Get.currentRoute.contains(Routes.liveNormal)) {
        if (videoWidth >= videoHeight) needChange = true;
      } else if (Get.currentRoute.contains(Routes.lqMatchDetail) ||
          Get.currentRoute.contains(Routes.zqMatchDetail)) {
        if (videoWidth < videoHeight) needChange = true;
      }
      var newHeight = width * videoHeight / videoWidth;
      if (newHeight != height && needChange) {
        height = newHeight;
        update();
      }
    });
    player.setOnTrackReady((playerId) {
      Logger().d(playerId);
    });
    var log = await player.getScalingMode();
    originBrightness = await ScreenBrightness().current;
    Logger().d("$log");
    super.onInit();
  }

  @override
  void onReady() async {
    await Future.delayed(const Duration(milliseconds: 200));
    if (autoPlay) play();
    _lifecycleListener = AppLifecycleListener(
      onResume: () {
        if (Get.find<ConfigService>().pushConfig.liveBackground == 0) {
          player.setMuted(false);
        }
      },
      onHide: () {
        if (Get.find<ConfigService>().pushConfig.liveBackground == 0) {
          player.setMuted(true);
        }
      },
    );
    super.onReady();
  }

  @override
  void onClose() {
    resetVolume();
    resetBrightness();
    player.destroy();
    _lifecycleListener?.dispose();
    super.onClose();
  }

  void resetVolume() {
    if (trueVolume == 0 && originVolume != 0) {
      VolumeController().setVolume(originVolume);
    }
  }

  void resetBrightness() {
    ScreenBrightness().setScreenBrightness(originBrightness);
  }

  void setPosition() async {
    await player.seekTo(slidePosition.toInt(), FlutterAvpdef.ACCURATE);
    if (onSlide) onSlide = false;
    if (status == PlayStatus.completion) {
      pauseToPlay();
    }
  }

  Future play() async {
    if (!setFirst) {
      await completer.future;
    } else {
      setFirst = false;
      update();
    }
    player.setUrl(url);
    try {
      player.prepare();
    } catch (e) {
      Logger().d("准备播放遇到错误$e");
    }
  }

  void pauseToPlay() {
    player.play();
    status = PlayStatus.started;
  }

  void pause() {
    player.pause();
    status = PlayStatus.paused;
  }

  void doRefresh() async {
    setFirst = true;
    currentViewId = null;
    player.reload();
    status = PlayStatus.initialized;
    play();
  }

  void setLoop(bool value) {
    player.setLoop(value);
  }

  void setMute(bool value) {
    player.setMuted(value);
    update();
  }

  String formTime() {
    var currentTime =
        DateTime.fromMillisecondsSinceEpoch(slidePosition.toInt(), isUtc: true);
    return <String>[
      if (currentTime.hour > 0) "${currentTime.hour}:",
      currentTime.formatedString('mm:ss')
    ].join();
  }

  onVolumnChanged(Offset offset) {
    //每移动10调一次音量
    int level = offset.dy ~/ 10;
    if (level != volumeLevel) {
      volumeLevel = level;
      double change = -offset.dy / 200;
      trueVolume += change;
      VolumeController().setVolume(trueVolume, showSystemUI: true);
    }
  }

  onBrightnessChanged(Offset offset) {
    int level = offset.dy ~/ 10;
    if (level != brightnessLevel) {
      brightnessLevel = level;
      double change = -offset.dy / 200;
      double brightness = 0;
      if (startBrightness + change > 1) {
        brightness = 1;
      } else if (startBrightness + change < 0) {
        brightness = 0;
      } else {
        brightness = startBrightness + change;
      }
      ScreenBrightness().setScreenBrightness(brightness);
    }
  }

  void setFit(bool isFit) {
    if (isFit) {
      player.setScalingMode(FlutterAvpdef.AVP_SCALINGMODE_SCALETOFILL);
    } else {
      player.setScalingMode(FlutterAvpdef.AVP_SCALINGMODE_SCALEASPECTFIT);
    }
    doRefresh();
  }

  void goSmall() {
    if (status == PlayStatus.started && duration == 0) {
      LiveFloatController.instance.show();
    }
  }

  Future setPlayerView(int viewId) async {
    if (_createTimer != null) {
      currentViewId = viewId;
      return;
    }
    player.setPlayerView(viewId);
    currentViewId = viewId;
    if (_completer != null) {
      completer.complete();
      _completer = null;
    } else {
      setFirst = true;
    }
    update();
    _createTimer = Timer(const Duration(milliseconds: 50), () {
      _createTimer?.cancel();
      _createTimer = null;
      update();
    });
  }
}
